From 92f5a40578f9f898b035db0a13d852c01e1eea77 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 4 Oct 2005 15:02:51 +0100 Subject: [PATCH] Allow EVTCHNOP_bind_{ipi,virq} to specify the vcpu to bind to. Previously the alloacted port was implicitly bound to the calling vcpu. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c | 4 ++++ tools/libxc/xc_evtchn.c | 3 ++- xen/common/event_channel.c | 13 ++++++++----- xen/include/public/event_channel.h | 11 +++++++---- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c index 99f928e1a3..647f1f240b 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c @@ -189,6 +189,7 @@ int bind_virq_to_irq(int virq) if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { op.cmd = EVTCHNOP_bind_virq; op.u.bind_virq.virq = virq; + op.u.bind_virq.vcpu = cpu; BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); evtchn = op.u.bind_virq.port; @@ -252,6 +253,7 @@ int bind_ipi_to_irq(int ipi) if ((evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == -1) { op.cmd = EVTCHNOP_bind_ipi; + op.u.bind_ipi.vcpu = cpu; BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); evtchn = op.u.bind_ipi.port; @@ -666,6 +668,7 @@ void irq_resume(void) /* Get a new binding from Xen. */ op.cmd = EVTCHNOP_bind_virq; op.u.bind_virq.virq = virq; + op.u.bind_virq.vcpu = 0; BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); evtchn = op.u.bind_virq.port; @@ -687,6 +690,7 @@ void irq_resume(void) /* Get a new binding from Xen. */ op.cmd = EVTCHNOP_bind_ipi; + op.u.bind_ipi.vcpu = 0; BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); evtchn = op.u.bind_ipi.port; diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c index 74e8468dd5..f7698d3541 100644 --- a/tools/libxc/xc_evtchn.c +++ b/tools/libxc/xc_evtchn.c @@ -90,7 +90,8 @@ int xc_evtchn_bind_virq(int xc_handle, op.cmd = EVTCHNOP_bind_virq; op.u.bind_virq.virq = (u32)virq; - + op.u.bind_virq.vcpu = 0; + if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 ) { if ( port != NULL ) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 6ad5c25788..8c413097ba 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -244,15 +244,15 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind) static long evtchn_bind_virq(evtchn_bind_virq_t *bind) { struct evtchn *chn; - struct vcpu *v = current; - struct domain *d = v->domain; + struct vcpu *v; + struct domain *d = current->domain; int port, virq = bind->virq; if ( virq >= ARRAY_SIZE(v->virq_to_evtchn) ) return -EINVAL; - if ( d->domain_id == 0 && virq >= VIRQ_CONSOLE ) - v = d->vcpu[0]; + if ( (v = d->vcpu[bind->vcpu]) == NULL ) + return -ENOENT; spin_lock(&d->evtchn_lock); @@ -288,13 +288,16 @@ static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind) struct domain *d = current->domain; int port; + if ( d->vcpu[bind->vcpu] == NULL ) + return -ENOENT; + spin_lock(&d->evtchn_lock); if ( (port = get_free_port(d)) >= 0 ) { chn = evtchn_from_port(d, port); chn->state = ECS_IPI; - chn->notify_vcpu_id = current->vcpu_id; + chn->notify_vcpu_id = bind->vcpu; } spin_unlock(&d->evtchn_lock); diff --git a/xen/include/public/event_channel.h b/xen/include/public/event_channel.h index d1629ec244..443be607f8 100644 --- a/xen/include/public/event_channel.h +++ b/xen/include/public/event_channel.h @@ -51,22 +51,24 @@ typedef struct evtchn_bind_interdomain { } evtchn_bind_interdomain_t; /* - * EVTCHNOP_bind_virq: Bind a local event channel to IRQ on calling vcpu. + * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ on specified + * vcpu. * NOTES: * 1. A virtual IRQ may be bound to at most one event channel per vcpu. - * 2. The allocated event channel is bound to the calling vcpu. The binding + * 2. The allocated event channel is bound to the specified vcpu. The binding * may not be changed. */ #define EVTCHNOP_bind_virq 1 typedef struct evtchn_bind_virq { /* IN parameters. */ u32 virq; + u32 vcpu; /* OUT parameters. */ u32 port; } evtchn_bind_virq_t; /* - * EVTCHNOP_bind_pirq: Bind a local event channel to IRQ . + * EVTCHNOP_bind_pirq: Bind a local event channel to PIRQ . * NOTES: * 1. A physical IRQ may be bound to at most one event channel per domain. * 2. Only a sufficiently-privileged domain may bind to a physical IRQ. @@ -84,11 +86,12 @@ typedef struct evtchn_bind_pirq { /* * EVTCHNOP_bind_ipi: Bind a local event channel to receive events. * NOTES: - * 1. The allocated event channel is bound to the calling vcpu. The binding + * 1. The allocated event channel is bound to the specified vcpu. The binding * may not be changed. */ #define EVTCHNOP_bind_ipi 7 typedef struct evtchn_bind_ipi { + u32 vcpu; /* OUT parameters. */ u32 port; } evtchn_bind_ipi_t; -- 2.30.2